#pragma once

#include <iostream>
#include <vector>
#include <queue>
#include <pthread.h>
#include "thread.hpp"
#include "lockguard.hpp"
#include "log.hpp"

using namespace zxf;

#define NUM 10

namespace zxf
{
    template <class T>
    class ThreadPool;

    template <class T>
    class ThreadData
    {
    public:
        ThreadData(ThreadPool<T> *tpthis, std::string threadname)
            : _tpthis(tpthis), _threadname(threadname)
        {
        }

        ThreadPool<T> *_tpthis;
        std::string _threadname;
    };

    template <class T>
    class ThreadPool
    {
    private:
        int _num;
        std::vector<Thread *> _threads; // 保存创建的线程
        std::queue<T> _task_queue;      // 保存任务列表
        pthread_mutex_t _mutex;         // 保护任务队列
        pthread_cond_t _cond;           // 线程阻塞的条件变量

    private:
        static void *handlertask(void *args) // 每个线程执行的函数
        {
            // sleep(3);
            // std::cout<<(args)<<std::endl;

            ThreadData<T> *data = static_cast<ThreadData<T> *>(args);
            while (true)
            {
                // data->_tpthis->lockqueue();
                T t;
                {
                    LockGuard lock(data->_tpthis->getmutex()); // RAII形式枷锁
                    while (data->_tpthis->queueempty())        // 这里只能是whi./sle , 不能是if
                    {
                        data->_tpthis->waitthread();
                    }
                    t = data->_tpthis->queuepop();
                }
                // data->_tpthis->unlockqueue();
                //std::cout << data->_threadname << "处理任务!!" << std::endl;
                logMessage(NORMAL, "%s:%d", "theadpool 处理了一个任务!!", 0);
                t();
            }
        }
        // 给队列加锁
        void lockqueue()
        {
            pthread_mutex_lock(&_mutex);
        }
        // 给队列解锁
        void unlockqueue()
        {
            pthread_mutex_unlock(&_mutex);
        }
        // 判断队列是否为空
        bool queueempty()
        {
            return _task_queue.empty();
        }
        // 在条件变量下等待
        void waitthread()
        {
            pthread_cond_wait(&_cond, &_mutex);
        }

        // 删除队列头部的数据
        T queuepop()
        {
            // 这个是内部接口
            // 不用加锁，因为在锁内部调用。
            T ret = _task_queue.front();
            _task_queue.pop();
            return ret;
        }

        // 唤醒一个线程
        void signalthread()
        {
            pthread_cond_signal(&_cond);
        }

        // 得到锁
        pthread_mutex_t *getmutex()
        {
            return &_mutex;
        }

    public:
        ThreadPool(int num = NUM)
            : _num(num)
        {
            // 初始化各种变量
            pthread_mutex_init(&_mutex, nullptr);
            pthread_cond_init(&_cond, nullptr);
            for (int i = 0; i < _num; ++i)
            {

                Thread *tp = new Thread(); // 这里实际上 啥也没干 只是给每一个线程对象创建了一个name
                _threads.push_back(tp);
            }
            // 创建NUM个线程对象
        }

        // 开始执行创建线程
        void start()
        {
            for (auto &e : _threads)
            {
                ThreadData<T> *data = new ThreadData<T>(this, e->getname());
                e->start(handlertask, (void *)data);
                // std::cout<<e<<" thread start.."<<std::endl;
                logMessage(NORMAL, "%s:%d", "theadpool  thread start..", 0);
            }
        }

        void push(T in)
        {
            // lockqueue();
            LockGuard lock = getmutex(); // 加锁
            _task_queue.push(in);
            // std::cout << "收到一个任务"<< std::endl;
            logMessage(NORMAL, "%s:%d", "theadpool 收到一个任务", 0);
            // std::cout << "收到任务：" << in.totaskstring() << std::endl;

            // 唤醒一个线程
            signalthread();
            // unlockqueue();
        }

        ~ThreadPool()
        {
            pthread_mutex_destroy(&_mutex);
            pthread_cond_destroy(&_cond);
            for (auto &e : _threads)
            {
                e->join();
                delete e;
            }
        }
    };
} // namespace zxf end!!!

// 懒汉模式, 线程安全

// template <class T>
// class ThreadPool
// {
//     typedef void *(*func_t)(void *);
//     static void *handlerTask(void *args)
//     {

//         ThreadPool<T> *th = static_cast<ThreadPool<T> *>(args);
//         while(true)
//         {
//             pthread_mutex_lock(&(th->_mutex));

//             while(th->_task_queue.size() == 0)
//             {
//                 pthread_cond_wait(&(th->_cond) ,&(th->_mutex));
//             }
//             T t = th->_task_queue.front();
//             th->_task_queue.pop();
//             pthread_mutex_unlock(&(th->_mutex));
//             t();//处理任务
//         }
//         return nullptr;
//     }

// public:
//     ThreadPool(pthread_t num = NUM) : _num(num)
//     {
//         pthread_mutex_init(&_mutex, nullptr);
//         pthread_cond_init(&_cond, nullptr);

//         for (int i = 0; i < _num; i++) // 创建num个线程
//         {
//             _threads.push_back(new Thread(handlerTask, this));
//         }
//     }
//     void start()
//     {
//         for(int i =0 ; i< _threads.size();i++)
//         {
//             _threads[i]->start();
//             std::cout<<_threads[i]->getname()<<"start..."<<std::endl;
//         }
//     }

//     void* PushTask(const T& in)
//     {
//         pthread_mutex_lock(&_mutex);
//         _task_queue.push(in);
//         pthread_cond_signal(&_cond);
//         pthread_mutex_unlock(&_mutex);
//     }

//     ~ThreadPool()
//     {
//         pthread_mutex_destroy(&_mutex);
//         pthread_cond_destroy(&_cond);
//         for (auto &t : _threads)
//         {
//             t->join();
//             delete t;
//         }
//     }

// private:
//     std::vector<Thread *> _threads; // 存放线程
//     int _num;                       // 线程的多少
//     std::queue<T> _task_queue;      // 存放任务的队列
//     pthread_mutex_t _mutex;         // 所有线程必须互斥的访问我们的的任务队列。
//     pthread_cond_t _cond;           // 线程阻塞的条件变量。在这个条件变量下等待。
// };
